Skip to main content

Integration

Implementing the Biometric Capture Session in a View-based UI

This example shows how to integrate the Biometric Capture Session to your project. The Biometric Capture Session extracts a frames collection from the camera preview.

This Example app uses ViewBinding, so enable it with the following (at the end of the android{} block):

buildFeatures {
viewBinding true
}

When prompted, click Sync Now, and we will be ready to use the Biometric Capture Session in our app.

Create a capture layout.

In the UI for this example app, we use the following layout structure:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".CaptureFragment">

<LinearLayout
android:id="@+id/ll_capture_session_view_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" />

<Button
android:id="@+id/btn_start_capture"
android:layout_width="170dp"
android:layout_height="50dp"
android:layout_gravity="center"
android:layout_marginTop="300dp"
android:textColor="#DBD7E4"
android:background="@color/colorPrimary"
android:visibility="gone"/>

</FrameLayout>

This LinealLayout hosts MBCaptureSessionView.

 <LinearLayout
android:id="@+id/ll_capture_session_view_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" />

The capture button is enabled when the capture process is not automatic.

  <Button
android:id="@+id/btn_start_capture"
android:layout_width="170dp"
android:layout_height="50dp"
android:layout_gravity="center"
android:layout_marginTop="300dp"
android:textColor="#DBD7E4"
android:background="@color/colorPrimary"
android:visibility="gone"/>

FrameCollectionViewModel updates and observes by using Livedata and ViewModelthe collection of frames contained by MBCaptureSessionResult.

class FrameCollectionViewModel : ViewModel(){

private val mutableFrameCollection = MutableLiveData<List<Bitmap?>>()
var frameCollection: LiveData<List<Bitmap?>> = mutableFrameCollection

fun setFrameCollection(frames: ArrayList<Bitmap?>) {
mutableFrameCollection.value = frames
}
}

Setup CaptureFragment.kt.

//CaptureFragment.kt
@SuppressLint("UnsafeOptInUsageError")
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
mBinding = FragmentCaptureBinding.inflate(inflater,container,false)


val options = MBCaptureSessionOptions.Builder().automaticCapture(false).build()

captureSessionService = MBCaptureSessionService(requireContext(), this, options, this)

mBinding.container.addView(captureSessionService!!.getCaptureSessionView())

captureSessionService!!.startCamera()


if (!captureSessionService!!.getAutomaticCapture()) {
mBinding.btnStartCapture.visibility = View.VISIBLE
mBinding.btnStartCapture.setOnClickListener {
captureSessionService!!.startCaptureSession()
}
}

return mBinding.root
}


override fun onCaptureFinished(result: MBCaptureSessionResult?){
requireActivity().runOnUiThread {
result?.let {
viewFrameCollection.setFrameCollection(it.frames)
findNavController().navigate(R.id.action_captureFragment_to_imagesFragment)
}
}
}


override fun onCaptureSessionStatusChanged(captureStatus: MBCaptureSessionStatus) {
//TODO implement feature with captureStatus update
}

override fun onWaitingToCapture(faceStatus: MBFaceStatus) {
//TODO implement feature with faceStatus update
}

override fun onFailure(errorEnum: MBCaptureSessionError) {
//TODO implement feature with errorEnum update
}

override fun onCaptureStarted() {
//TODO implement feature when capture start
}

Creates a CaptureFragment viewBinding instance:

 private lateinit var mBinding : FragmentCaptureBinding

Creates an instance of MBCaptureSessionInstance. This is the capture session's entry point configuration..

 private var captureSessionService: MBCaptureSessionService? = null

Create an instance of MBCaptureSessionOptions builder. This is the capture session's entry point configuration and it has its own default values . In this case the automaticCapture is set to false and that means the capture is manual.

  val options = MBCaptureSessionOptions.Builder().automaticCapture(false).build()

MBCaptureSessionInstance initialization.

  captureSessionService = MBCaptureSessionService(requireContext(), this, options, this)

Adds the CaptureSessionView as view child to our CaptureFragment.

  mBinding.llCaptureSessionViewContainer.addView(captureSessionService!!.getCaptureSessionView())

Starts Camera if camera permission is granted. It is very important to verify the camera permission to get the feature up running.

  captureSessionService!!.startCamera()

This block of code enables the capture button if automaticCapture is set to false mining the capture process is manual, or disables it if the automaticCapture is set to true.

   if (!captureSessionService!!.getAutomaticCapture()) {
mBinding.btnStartCapture.visibility = View.VISIBLE
mBinding.btnStartCapture.setOnClickListener {
captureSessionService!!.startCaptureSession()
}
}

The function onCaptureFinished gets a result of the capture process if it is successfully finished. result contains a list of nullable Bitmaps. In this case send it as argument to another screen by using ViewModel and LiveData. And then I start that another activity.

  override fun onCaptureFinished(result: MBCaptureSessionResult?){
requireActivity().runOnUiThread {
result?.let {
viewFrameCollection.setFrameCollection(it.frames)
findNavController().navigate(R.id.action_captureFragment_to_imagesFragment)
}
}
}

The function is executed every time the capture process changes its state. MBCaptureSessionStatus describes those states.

  override fun onCaptureSessionStatusChanged(captureStatus: MBCaptureSessionStatus) {
//TODO implement feature with captureStatus update
}

The function onWaitingToCapture is executed every time the face state changes. MBFaceStatus describes the state of the face in the camera preview.

  override fun onWaitingToCapture(faceStatus: MBFaceStatus) {
//TODO implement feature with faceStatus update
}

The function onFailure is executed when the capture process fails. MBCaptureSessionError tells the type of error that occurred.

  override fun onFailure(errorEnum: MBCaptureSessionError) {
//TODO implement feature with errorEnum update
}

The method onCaptureStarted is executed every time a face is valid and starts capturing.

  override fun onCaptureStarted() {
//TODO implement feature when capture start
}